﻿using Microsoft.MachineLearning.CommandLine;
using Microsoft.TMSN.TMSNlearn;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;

namespace myAC.TLC
{
    class TLCAPI
    {
        /// <summary>
        /// Not finished yet
        /// </summary>
        public static void TrainAndSaveModel()
        {
            string trainDatafile = @"E:\myWork\NewAutoClassification\myAC\Data\635300855900007379.input.txt";
            // informs tlc how to parse the data
            string instanceSettings = @"header-;text:1,2;label:0";

            //E:\Projects\AF\O365AC\TLC\TL.exe /c cv /k:5 635297859751206729.input.txt /inst TextInstances{sparse=- text=1,2 label=0} /cl OVA /summary:+ /sf:E:\Projects\AF\O365AC\Result\0.summary.txt /o:E:\Projects\AF\O365AC\Result\0.inst.txt /tlc /trsess:1

            ListInstances.Arguments args = new ListInstances.Arguments();
            ///http://answer/Questions/418598/-
            args.baseInstancesClass = new SubComponent(TlcTextInstances.LoadName, instanceSettings);
            ListInstances instances = new ListInstances(args, trainDatafile, null);

            // start with discovering the factory to get a trainer. We use reflection to discover the factory.
            // if factory is null: 
            //   please check if the name is right or if the dll containing the learner is referenced
            //   Eg: if you want to use the BinaryNeuralNetwork as the trainer : 
            //   make sure you have added a reference to NeuralNetworks.dll

            string factoryName = "FastRankClassification"; // OR "LogisticRegression" OR "BinaryNeuralNetwork"

            // A type-safe way to get the trainer name
            //factoryName = NeuralNetworks.BinaryNeuralNetworkFactory.Instance.LoadName;
            factoryName = LinearSVMFactory.Instance.LoadName;

            var factory = ReflectionUtils.FindFactory<float>(factoryName);
            var arg = factory.CreateArguments();

            // this is how you pass the arguments to the trainer
            string[] trainerArgs = new string[] { "/k:5", trainDatafile, "/inst TextInstances{sparse=- text=1,2 label=0}", };
            PredictionUtil.ParseArguments(arg, trainerArgs);

            var trainer = factory.CreateTrainer(arg, new TrainHost(new Random(1), 0));
            trainer.Train(instances);

            // Once training is done - we need to get a Predictor (model) out of the trainer.
            // The Predictor.Predict(Instance) interface can be used to get a prediction
            var predictor = trainer.CreatePredictor();

            // The predictor is a serializable object that you can serialize as is to a file(binary format)
            string fileName = Path.GetTempFileName();
            using (Stream stream = new FileStream(fileName, FileMode.Create))
            {
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(stream, predictor);
            }

            // Saving as text/ini/code. 
            // PredictorUtils class has a set of static functions which let users save 
            // the predictor in different formats.
            // Some predictors cannot be saved in text/code/ini though.
        }

    }
}
